package com.insight.modules.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.common.base.Joiner;
import com.insight.modules.system.entity.*;
import com.insight.modules.system.mapper.*;
import com.insight.modules.system.service.*;
import com.yuanqiao.insight.acore.depart.entity.SysDepart;
import com.yuanqiao.insight.acore.depart.mapper.SysDepartMapper;
import com.yuanqiao.insight.acore.system.entity.SysDict;
import com.yuanqiao.insight.acore.system.service.ISysDictService;
import com.yuanqiao.insight.common.util.common.LocalCacheUtils;
import com.yuanqiao.insight.modules.notice.entity.SysNoticeConfig;
import com.yuanqiao.insight.modules.notice.entity.SysNoticeExtend;
import com.yuanqiao.insight.modules.notice.entity.SysNoticeTemplate;
import com.yuanqiao.insight.modules.notice.service.ISysNoticeConfigService;
import com.yuanqiao.insight.modules.notice.service.impl.SysNoticeTemplateServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.insight.modules.system.entity.*;
import org.insight.modules.system.mapper.*;
import org.insight.modules.system.service.*;
import com.insight.common.api.dto.OnlineAuthDTO;
import com.insight.common.api.dto.message.*;
import com.insight.common.aspect.UrlMatchEnum;
import com.insight.common.constant.CacheConstant;
import com.insight.common.constant.CommonConstant;
import com.insight.common.constant.DataBaseConstant;
import com.insight.common.exception.JeecgBootException;
import com.insight.common.message.websocket.WebSocket;
import com.insight.common.message.webssh.pojo.WebsocketConst;
import com.insight.common.mq.RedisMq;
import com.insight.common.mq.stream.Streams;
import com.insight.common.system.api.ISysBaseAPI;
import com.insight.common.system.query.QueryGenerator;
import com.insight.common.system.vo.*;
import com.insight.common.util.*;
import com.insight.modules.message.entity.SysMessageTemplate;
import com.insight.modules.message.service.ISysMessageTemplateService;
import com.insight.modules.system.entity.*;
import com.insight.modules.system.mapper.*;
import com.insight.modules.system.service.*;
import com.insight.modules.system.util.SecurityUtil;
import com.insight.modules.system.vo.SysUserDepVo;
import com.insight.modules.system.vo.SysUserRoleVO;
import org.jeecgframework.poi.excel.ExcelExportUtil;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ObjectUtils;
import org.springframework.util.PathMatcher;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 底层共通业务API，提供其他独立模块调用
 * @Author: scott
 * @Date:2019-4-20
 * @Version:V1.0
 */
@Slf4j
@Service
@Primary
public class SysBaseApiImpl implements ISysBaseAPI {
    /**
     * 当前系统数据库类型
     */
    private static String DB_TYPE = "";
    @Autowired
    private ISysMessageTemplateService sysMessageTemplateService;
    @Resource
    private SysUserMapper userMapper;
    @Resource
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private ISysDepartService sysDepartService;
    @Autowired
    private ISysDictService sysDictService;
    @Autowired
    private ISysAnnouncementService sysAnnouncementService;
    @Resource
    private SysAnnouncementMapper sysAnnouncementMapper;
    @Resource
    private SysAnnouncementSendMapper sysAnnouncementSendMapper;
    @Resource
    private SysRoleMapper roleMapper;
    @Resource
    private SysDepartMapper departMapper;
    @Resource
    private SysCategoryMapper categoryMapper;
    @Autowired
    private ISysDataSourceService dataSourceService;
    @Autowired
    private ISysUserDepartService sysUserDepartService;
    @Resource
    private SysPermissionMapper sysPermissionMapper;
    @Autowired
    ISysPermissionService iSysPermissionService;
    @Autowired
    private ISysPermissionDataRuleService sysPermissionDataRuleService;
    @Autowired
    ISysCategoryService sysCategoryService;
    @Autowired
    private RedisMq redisMq;
    @Autowired
    private SysNoticeTemplateServiceImpl sysNoticeTemplateService;
    @Autowired
    private ISysNoticeConfigService noticeConfigService;
    @Autowired
    private SysRolePermissionMapper sysRolePermissionMapper;

    private static final LocalCacheUtils cacheUtils = LocalCacheUtils.getInstance();

    @Override
    @Cacheable(cacheNames = CacheConstant.SYS_USERS_CACHE, key = "#username")
    public LoginUser getUserByName(String username) {
        if (oConvertUtils.isEmpty(username)) {
            return null;
        }
        LoginUser loginUser = new LoginUser();
        SysUsers sysUser = userMapper.getUserByName(username);
        if (sysUser == null) {
            return null;
        }
        //通过用户名称获取用户的角色
        BeanUtils.copyProperties(sysUser, loginUser);
        List<String> roleCodes = sysUserRoleMapper.getRoleCodeByUserName(username);
        loginUser.setRoleCodes(String.join(",", roleCodes));
        return loginUser;
    }


    @Override
    public List<LoginUser> getLoginUserByNames(List<String> users) {
        List<LoginUser> loginUserByNames = userMapper.getLoginUserByNames(users);
        if (ObjectUtils.isEmpty(loginUserByNames)) {
            return null;
        }
        return loginUserByNames;
    }

    @Override
    public List<String> getTreeDepIdsByDepId(String departId) {
        return sysDepartService.getSubDepIdsByDepId(departId);
    }

    @Override
    public List<SysPermissionDataRuleModel> queryPermissionDataRule(String component, String requestPath, String username) {
        List<SysPermission> currentSyspermission = null;
        if (oConvertUtils.isNotEmpty(component)) {
            //1.通过注解属性pageComponent 获取菜单
            LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>();
            query.eq(SysPermission::getDelFlag, 0);
            query.eq(SysPermission::getComponent, component);
            currentSyspermission = sysPermissionMapper.selectList(query);
        } else {
            //1.直接通过前端请求地址查询菜单
            LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>();
            query.eq(SysPermission::getMenuType, 2);
            query.eq(SysPermission::getDelFlag, 0);
            query.eq(SysPermission::getUrl, requestPath);
            currentSyspermission = sysPermissionMapper.selectList(query);
            //2.未找到 再通过自定义匹配URL 获取菜单
            if (currentSyspermission == null || currentSyspermission.size() == 0) {
                //通过自定义URL匹配规则 获取菜单（实现通过菜单配置数据权限规则，实际上针对获取数据接口进行数据规则控制）
                String userMatchUrl = UrlMatchEnum.getMatchResultByUrl(requestPath);
                LambdaQueryWrapper<SysPermission> queryQserMatch = new LambdaQueryWrapper<SysPermission>();
                queryQserMatch.eq(SysPermission::getMenuType, 1);
                queryQserMatch.eq(SysPermission::getDelFlag, 0);
                queryQserMatch.eq(SysPermission::getUrl, userMatchUrl);
                if (oConvertUtils.isNotEmpty(userMatchUrl)) {
                    currentSyspermission = sysPermissionMapper.selectList(queryQserMatch);
                }
            }
            //3.未找到 再通过正则匹配获取菜单
            if (currentSyspermission == null || currentSyspermission.size() == 0) {
                //通过正则匹配权限配置
                String regUrl = getRegexpUrl(requestPath);
                if (regUrl != null) {
                    currentSyspermission = sysPermissionMapper.selectList(new LambdaQueryWrapper<SysPermission>().eq(SysPermission::getMenuType, 2).eq(SysPermission::getUrl, regUrl).eq(SysPermission::getDelFlag, 0));
                }
            }
        }
        if (currentSyspermission != null && currentSyspermission.size() > 0) {
            List<SysPermissionDataRuleModel> dataRules = new ArrayList<SysPermissionDataRuleModel>();
            for (SysPermission sysPermission : currentSyspermission) {
                // update-begin--Author:scott Date:20191119 for：数据权限规则编码不规范，项目存在相同包名和类名 #722
                List<SysPermissionDataRule> temp = sysPermissionDataRuleService.queryPermissionDataRules(username, sysPermission.getId());
                if (temp != null && temp.size() > 0) {
                    //dataRules.addAll(temp);
                    dataRules = oConvertUtils.entityListToModelList(temp, SysPermissionDataRuleModel.class);
                }
                // update-end--Author:scott Date:20191119 for：数据权限规则编码不规范，项目存在相同包名和类名 #722
            }
            return dataRules;
        }
        return null;
    }

    /**
     * 匹配前端传过来的地址 匹配成功返回正则地址
     * AntPathMatcher匹配地址
     * ()* 匹配0个或多个字符
     * ()**匹配0个或多个目录
     */
    private String getRegexpUrl(String url) {
        List<String> list = sysPermissionMapper.queryPermissionUrlWithStar();
        if (list != null && list.size() > 0) {
            for (String p : list) {
                PathMatcher matcher = new AntPathMatcher();
                if (matcher.match(p, url)) {
                    return p;
                }
            }
        }
        return null;
    }

    @Override
    public String parseTemplateByCode(String templateCode, Map<String, String> map) {
        SysNoticeTemplate sysNoticeTemplate = sysNoticeTemplateService.getById(templateCode);
        if (sysNoticeTemplate == null) {
            throw new JeecgBootException("消息模板不存在，模板编码：" + templateCode);
        }
        //模板内容
        String content = sysNoticeTemplate.getTemplate();
        if (map != null) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                String str = "${" + entry.getKey() + "}";
                content = content.replace(str, entry.getValue());
            }
        }
        return content;
    }

    @Override
    public SysUserCacheInfo getCacheUser(String username) {
        SysUserCacheInfo info = new SysUserCacheInfo();
        info.setOneDepart(true);
        LoginUser user = this.getUserByName(username);
        if (user != null) {
            info.setSysUserCode(user.getUsername());
            info.setSysUserName(user.getRealname());
            info.setSysOrgCode(user.getOrgCode());
        }
        //多部门支持in查询
        List<SysDepart> list = departMapper.queryUserDeparts(user.getId());
        List<String> sysMultiOrgCode = new ArrayList<String>();
        if (list == null || list.size() == 0) {
            //当前用户无部门
            //sysMultiOrgCode.add("0");
        } else if (list.size() == 1) {
            sysMultiOrgCode.add(list.get(0).getOrgCode());
        } else {
            info.setOneDepart(false);
            for (SysDepart dpt : list) {
                sysMultiOrgCode.add(dpt.getOrgCode());
            }
        }
        info.setSysMultiOrgCode(sysMultiOrgCode);
        return info;
    }


    /**
     * 加密保存公用方法
     *
     * @param clazz      类
     * @param title      文件名称
     * @param exportList 导出数据
     */
    @Override
    public Map<String, Object> saveZipPwd(Class clazz, String title, List exportList, String bizPath) {
        ExportParams exportParams1 = new ExportParams();
        exportParams1.setSheetName(title);
        Map<String, Object> deptDataMap = new HashMap<>(4);
        // title的参数为ExportParams类型
        deptDataMap.put("title", exportParams1);
        // 模版导出对应得实体类型
        deptDataMap.put("entity", clazz);
        // sheet中要填充得数据
        Collections.reverse(exportList);
        deptDataMap.put("data", exportList);

        List<Map<String, Object>> sheetsList = new ArrayList<>();
        sheetsList.add(deptDataMap);
        // 执行方法
        Workbook workbook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.HSSF);
        return CommonUtils.saveExcel(title + ".xls", workbook, bizPath);
    }

    @Override
    public Map<String, Object> saveZipPwdWithExportFields(Class clazz, String title, List exportList, String bizPath, String exportFieldStr) {
        ExportParams exportParams = new org.jeecgframework.poi.excel.entity.ExportParams();
        exportParams.setSheetName(title);
        String[] exportFields = null;
        if (StringUtils.isNotEmpty(exportFieldStr)) {
            exportFields = exportFieldStr.split(",");
        }

        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, clazz, exportList, exportFields);
        return CommonUtils.saveExcel(title + ".xls", workbook, bizPath);
    }

    @Override
    public LoginUser getUserById(String id) {
        if (oConvertUtils.isEmpty(id)) {
            return null;
        }
        LoginUser loginUser = new LoginUser();
        SysUsers sysUser = userMapper.selectById(id);
        if (sysUser == null) {
            return null;
        }
        BeanUtils.copyProperties(sysUser, loginUser);
        return loginUser;
    }

    @Override
    public List<String> getRolesByUsername(String username) {
        return sysUserRoleMapper.getRoleByUserName(username);
    }

    @Override
    public List<String> getDepartIdsByUsername(String username) {
        List<SysDepart> list = sysDepartService.queryDepartsByUsername(username);
        List<String> result = new ArrayList<>(list.size());
        for (SysDepart depart : list) {
            result.add(depart.getId());
        }
        return result;
    }

    @Override
    public List<String> getDepartNamesByUsername(String username) {
        List<SysDepart> list = sysDepartService.queryDepartsByUsername(username);
        List<String> result = new ArrayList<>(list.size());
        for (SysDepart depart : list) {
            result.add(depart.getDepartName());
        }
        return result;
    }

    @Override
    public DictModel getParentDepartId(String departId) {
        SysDepart depart = departMapper.getParentDepartId(departId);
        DictModel model = new DictModel(depart.getId(), depart.getParentId());
        return model;
    }

    @Override
    @Cacheable(value = CacheConstant.SYS_DICT_CACHE, key = "#code")
    public List<DictModel> queryDictItemsByCode(String code) {
        return sysDictService.queryDictItemsByCode(code);
    }

    @Override
    public List<DictModel> queryTableDictItemsByCode(String table, String text, String code) {
        //update-begin-author:taoyan date:20200820 for:【Online+系统】字典表加权限控制机制逻辑，想法不错 LOWCOD-799
        if (table.indexOf("#{") >= 0) {
            table = QueryGenerator.getSqlRuleValue(table);
        }
        //update-end-author:taoyan date:20200820 for:【Online+系统】字典表加权限控制机制逻辑，想法不错 LOWCOD-799
        return sysDictService.queryTableDictItemsByCode(table, text, code);
    }

    @Override
    public List<DictModel> queryAllDepartBackDictModel() {
        return sysDictService.queryAllDepartBackDictModel();
    }

    @Override
    public void sendSysAnnouncement(MessageDTO message) {
        this.sendSysAnnouncement(message.getFromUser(),
                message.getToUser(),
                message.getTitle(),
                message.getContent(),
                message.getCategory(),
                message.getPriority());
    }

    @Override
    public void sendSysAnnouncement(String fromUser, String toUser, String title, String msgContent, Integer priority) {
        this.sendSysAnnouncement(fromUser, toUser, title, msgContent, CommonConstant.MSG_CATEGORY_2, priority);
    }


    @Override
    public void sendBusAnnouncement(BusMessageDTO message) {
        sendBusAnnouncement(message.getFromUser(),
                message.getToUser(),
                message.getTitle(),
                message.getContent(),
                message.getCategory(),
                message.getBusType(),
                message.getBusId(),
                message.getPriority());
    }

    @Override
    public void sendTemplateAnnouncement(TemplateMessageDTO message) {
        String templateCode = message.getTemplateCode();
        String title = message.getTitle();
        Map<String, String> map = message.getTemplateParam();
        String fromUser = message.getFromUser();
        String toUser = message.getToUser();

        List<SysMessageTemplate> sysSmsTemplates = sysMessageTemplateService.selectByCode(templateCode);
        if (sysSmsTemplates == null || sysSmsTemplates.size() == 0) {
            throw new JeecgBootException("消息模板不存在，模板编码：" + templateCode);
        }
        SysMessageTemplate sysSmsTemplate = sysSmsTemplates.get(0);
        //模板标题
        title = title == null ? sysSmsTemplate.getTemplateName() : title;
        //模板内容
        String content = sysSmsTemplate.getTemplateContent();
        if (map != null) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                String str = "${" + entry.getKey() + "}";
                title = title.replace(str, entry.getValue());
                content = content.replace(str, entry.getValue());
            }
        }

        SysAnnouncement announcement = new SysAnnouncement();
        announcement.setTitile(title);
        announcement.setMsgContent(content);
        announcement.setSender(fromUser);
        announcement.setPriority(CommonConstant.PRIORITY_M);
        announcement.setMsgType(CommonConstant.MSG_TYPE_UESR);
        announcement.setSendStatus(CommonConstant.HAS_SEND);
        announcement.setSendTime(new Date());
        announcement.setMsgCategory(CommonConstant.MSG_CATEGORY_2);
        announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
        sysAnnouncementMapper.insert(announcement);
        // 2.插入用户通告阅读标记表记录
        String userId = toUser;
        String[] userIds = userId.split(",");
        String anntId = announcement.getId();
        for (int i = 0; i < userIds.length; i++) {
            if (oConvertUtils.isNotEmpty(userIds[i])) {
                SysUsers sysUser = userMapper.getUserByName(userIds[i]);
                if (sysUser == null) {
                    continue;
                }
                SysAnnouncementSend announcementSend = new SysAnnouncementSend();
                announcementSend.setAnntId(anntId);
                announcementSend.setUserId(sysUser.getId());
                announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
                sysAnnouncementSendMapper.insert(announcementSend);
                JSONObject obj = new JSONObject();
                obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
                obj.put(WebsocketConst.MSG_USER_ID, sysUser.getId());
                obj.put(WebsocketConst.MSG_ID, announcement.getId());
                obj.put(WebsocketConst.MSG_TXT, announcement.getTitile());
                WebSocket.sendOneMessage(sysUser.getId(), obj.toJSONString());
            }
        }

    }

    @Override
    public void sendBusTemplateAnnouncement(BusTemplateMessageDTO message) {
        String templateCode = message.getTemplateCode();
        String title = message.getTitle();
        Map<String, String> map = message.getTemplateParam();
        String fromUser = message.getFromUser();
        String toUser = message.getToUser();
        String busId = message.getBusId();
        String busType = message.getBusType();
        String busMap = message.getBusMap();
        List<SysMessageTemplate> sysSmsTemplates = sysMessageTemplateService.selectByCode(templateCode);
        if (sysSmsTemplates == null || sysSmsTemplates.size() == 0) {
            throw new JeecgBootException("消息模板不存在，模板编码：" + templateCode);
        }
        SysMessageTemplate sysSmsTemplate = sysSmsTemplates.get(0);
        //模板标题
        title = title == null ? sysSmsTemplate.getTemplateName() : title;
        //模板内容
        String content = sysSmsTemplate.getTemplateContent();
        if (map != null) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                String str = "${" + entry.getKey() + "}";
                title = title.replace(str, entry.getValue());
                content = content.replace(str, entry.getValue());
            }
        }
        SysAnnouncement announcement = new SysAnnouncement();
        announcement.setTitile(title);
        announcement.setMsgContent(content);
        announcement.setSender(fromUser);
        announcement.setPriority(CommonConstant.PRIORITY_M);
        announcement.setMsgType(CommonConstant.MSG_TYPE_UESR);
        announcement.setSendStatus(CommonConstant.HAS_SEND);
        announcement.setSendTime(new Date());
        announcement.setMsgCategory(CommonConstant.MSG_CATEGORY_2);
        announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
        announcement.setBusId(busId);
        announcement.setBusType(busType);
        announcement.setUserIds(toUser);
        announcement.setBusMap(busMap);
        announcement.setOpenType(SysAnnmentTypeEnum.getByType(busType).getOpenType());
        announcement.setOpenPage(SysAnnmentTypeEnum.getByType(busType).getOpenPage());
        sysAnnouncementService.saveAnnouncement(announcement);
        // 3.发布通知
        JSONObject jsonOut = new JSONObject();
        jsonOut.put("messageType", "notice");
        jsonOut.put("data", announcement);
        String[] userIds = toUser.split(",");
        WebSocket.sendMoreMessage(userIds, jsonOut.toJSONString());

		/*sysAnnouncementMapper.insert(announcement);
		// 2.插入用户通告阅读标记表记录
		String userId = toUser;
		String[] userIds = userId.split(",");
		String anntId = announcement.getId();
		for(int i=0;i<userIds.length;i++) {
			if(oConvertUtils.isNotEmpty(userIds[i])) {
				SysUsers sysUser = userMapper.getUserByName(userIds[i]);
				if(sysUser==null) {
					continue;
				}
				SysAnnouncementSend announcementSend = new SysAnnouncementSend();
				announcementSend.setAnntId(anntId);
				announcementSend.setUserId(sysUser.getId());
				announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
				sysAnnouncementSendMapper.insert(announcementSend);
				JSONObject obj = new JSONObject();
				obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
				obj.put(WebsocketConst.MSG_USER_ID, sysUser.getId());
				obj.put(WebsocketConst.MSG_ID, announcement.getId());
				obj.put(WebsocketConst.MSG_TXT, announcement.getTitile());
				WebSocket.sendOneMessage(sysUser.getId(), obj.toJSONString());
			}
		}*/
    }

    @Override
    public String parseTemplateByCode(TemplateDTO templateDTO) {
        String templateCode = templateDTO.getTemplateCode();
        Map<String, String> map = templateDTO.getTemplateParam();
        List<SysMessageTemplate> sysSmsTemplates = sysMessageTemplateService.selectByCode(templateCode);
        if (sysSmsTemplates == null || sysSmsTemplates.size() == 0) {
            throw new JeecgBootException("消息模板不存在，模板编码：" + templateCode);
        }
        SysMessageTemplate sysSmsTemplate = sysSmsTemplates.get(0);
        //模板内容
        String content = sysSmsTemplate.getTemplateContent();
        if (map != null) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                String str = "${" + entry.getKey() + "}";
                content = content.replace(str, entry.getValue());
            }
        }
        return content;
    }

    @Override
    public void updateSysAnnounReadFlag(String busType, String busId) {
        SysAnnouncement announcement = sysAnnouncementMapper.selectOne(new QueryWrapper<SysAnnouncement>().eq("bus_type", busType).eq("bus_id", busId));
        if (announcement != null) {
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            String userId = sysUser.getId();
            LambdaUpdateWrapper<SysAnnouncementSend> updateWrapper = new UpdateWrapper().lambda();
            updateWrapper.set(SysAnnouncementSend::getReadFlag, CommonConstant.HAS_READ_FLAG);
            updateWrapper.set(SysAnnouncementSend::getReadTime, new Date());
            updateWrapper.last("where annt_id ='" + announcement.getId() + "' and user_id ='" + userId + "'");
            SysAnnouncementSend announcementSend = new SysAnnouncementSend();
            sysAnnouncementSendMapper.update(announcementSend, updateWrapper);
        }
    }

    /**
     * 获取数据库类型
     *
     * @param dataSource
     * @return
     * @throws SQLException
     */
    private String getDatabaseTypeByDataSource(DataSource dataSource) throws SQLException {
        if ("".equals(DB_TYPE)) {
            if (dataSource == null) {
                throw new SQLException("数据源为空");
            }
            Connection connection = dataSource.getConnection();
            try {
                DatabaseMetaData md = connection.getMetaData();
                if (md == null) {
                    throw new SQLException("无法获取数据库元数据");
                }
                String dbType = md.getDatabaseProductName().toLowerCase();
                if (dbType.indexOf("mysql") >= 0) {
                    DB_TYPE = DataBaseConstant.DB_TYPE_MYSQL;
                } else if (dbType.indexOf("oracle") >= 0) {
                    DB_TYPE = DataBaseConstant.DB_TYPE_ORACLE;
                } else if (dbType.indexOf("sqlserver") >= 0 || dbType.indexOf("sql server") >= 0) {
                    DB_TYPE = DataBaseConstant.DB_TYPE_SQLSERVER;
                } else if (dbType.indexOf("postgresql") >= 0) {
                    DB_TYPE = DataBaseConstant.DB_TYPE_POSTGRESQL;
                } else {
                    throw new JeecgBootException("数据库类型:[" + dbType + "]不识别!");
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
        }
        return DB_TYPE;
    }

    @Override
    public List<DictModel> queryAllDict() {
        // 查询并排序
        QueryWrapper<SysDict> queryWrapper = new QueryWrapper<SysDict>();
        queryWrapper.orderByAsc("create_time");
        List<SysDict> dicts = sysDictService.list(queryWrapper);
        // 封装成 model
        List<DictModel> list = new ArrayList<DictModel>();
        for (SysDict dict : dicts) {
            list.add(new DictModel(dict.getDictCode(), dict.getDictName()));
        }

        return list;
    }

    @Override
    public List<SysCategoryModel> queryAllDSysCategory() {
        List<SysCategory> ls = categoryMapper.selectList(null);
        List<SysCategoryModel> res = oConvertUtils.entityListToModelList(ls, SysCategoryModel.class);
        return res;
    }

    @Override
    public List<DictModel> queryFilterTableDictInfo(String table, String text, String code, String filterSql) {
        return sysDictService.queryTableDictItemsByCodeAndFilter(table, text, code, filterSql);
    }

    @Override
    public List<String> queryTableDictByKeys(String table, String text, String code, String[] keyArray) {
        return sysDictService.queryTableDictByKeys(table, text, code, Joiner.on(",").join(keyArray));
    }

    @Override
    public List<ComboModel> queryAllUserBackCombo() {
        List<ComboModel> list = new ArrayList<ComboModel>();
        List<SysUsers> userList = userMapper.selectList(new QueryWrapper<SysUsers>().eq("status", 1).eq("del_flag", 0));
        for (SysUsers user : userList) {
            ComboModel model = new ComboModel();
            model.setTitle(user.getRealname());
            model.setId(user.getId());
            model.setUsername(user.getUsername());
            list.add(model);
        }
        return list;
    }

    @Override
    public JSONObject queryAllUser(String userIds, Integer pageNo, Integer pageSize) {
        JSONObject json = new JSONObject();
        QueryWrapper<SysUsers> queryWrapper = new QueryWrapper<SysUsers>().eq("status", 1).eq("del_flag", 0);
        List<ComboModel> list = new ArrayList<ComboModel>();
        Page<SysUsers> page = new Page<SysUsers>(pageNo, pageSize);
        IPage<SysUsers> pageList = userMapper.selectPage(page, queryWrapper);
        for (SysUsers user : pageList.getRecords()) {
            ComboModel model = new ComboModel();
            model.setUsername(user.getUsername());
            model.setTitle(user.getRealname());
            model.setId(user.getId());
            model.setEmail(user.getEmail());
            if (oConvertUtils.isNotEmpty(userIds)) {
                String[] temp = userIds.split(",");
                for (int i = 0; i < temp.length; i++) {
                    if (temp[i].equals(user.getId())) {
                        model.setChecked(true);
                    }
                }
            }
            list.add(model);
        }
        json.put("list", list);
        json.put("total", pageList.getTotal());
        return json;
    }

    @Override
    public List<ComboModel> queryAllUser() {
        List<ComboModel> list = new ArrayList<ComboModel>();
        //List<SysUsers> userList = userMapper.selectList(new QueryWrapper<SysUsers>().eq("status",'1').eq("del_flag",'0'));
        String status = "1";
        String del_flag = "0";
        List<SysUsers> userList = userMapper.selectUserList(status, del_flag);
        for (SysUsers user : userList) {
            ComboModel model = new ComboModel();
            model.setTitle(user.getRealname());
            model.setId(user.getId());
            model.setUsername(user.getUsername());
            list.add(model);
        }
        return list;
    }

    @Override
    public List<ComboModel> queryAllRole() {
        List<ComboModel> list = new ArrayList<ComboModel>();
        List<SysRole> roleList = roleMapper.selectList(new QueryWrapper<SysRole>());
        for (SysRole role : roleList) {
            ComboModel model = new ComboModel();
            model.setTitle(role.getRoleName());
            model.setId(role.getId());
            list.add(model);
        }
        return list;
    }

    @Override
    public List<ComboModel> queryAllRole(String[] roleIds) {
        List<ComboModel> list = new ArrayList<ComboModel>();
        List<SysRole> roleList = roleMapper.selectList(new QueryWrapper<SysRole>());
        for (SysRole role : roleList) {
            ComboModel model = new ComboModel();
            model.setTitle(role.getRoleName());
            model.setId(role.getId());
            model.setRoleCode(role.getRoleCode());
            if (oConvertUtils.isNotEmpty(roleIds)) {
                for (int i = 0; i < roleIds.length; i++) {
                    if (roleIds[i].equals(role.getId())) {
                        model.setChecked(true);
                    }
                }
            }
            list.add(model);
        }
        return list;
    }

    @Override
    public List<String> getRoleIdsByUsername(String username) {
        return sysUserRoleMapper.getRoleIdByUserName(username);
    }


    @Override
    public List<String> getRoleCodeByUsername(String username) {
        return sysUserRoleMapper.getRoleCodeByUserName(username);
    }

    @Override
    public List<String> getUsernameByRoleCode(String roleCode) {
        return sysUserRoleMapper.getUsernameByRoleCode(roleCode);
    }

    @Override
    public List<String> getUsernameByRoleCodes(List<String> roleCodes) {
        return sysUserRoleMapper.getUsernameByRoleCodes(roleCodes);
    }

    @Override
    public String getDepartIdsByOrgCode(String orgCode) {
        return departMapper.queryDepartIdByOrgCode(orgCode);
    }

    @Override
    public List<SysDepartModel> getAllSysDepart() {
        List<SysDepartModel> departModelList = new ArrayList<SysDepartModel>();
        List<SysDepart> departList = departMapper.selectList(new QueryWrapper<SysDepart>().eq("del_flag", "0"));
        for (SysDepart depart : departList) {
            SysDepartModel model = new SysDepartModel();
            BeanUtils.copyProperties(depart, model);
            departModelList.add(model);
        }
        return departModelList;
    }

    @Override
    public DynamicDataSourceModel getDynamicDbSourceById(String dbSourceId) {
        SysDataSource dbSource = dataSourceService.getById(dbSourceId);
        if (dbSource != null && StringUtils.isNotBlank(dbSource.getDbPassword())) {
            String dbPassword = dbSource.getDbPassword();
            String decodedStr = SecurityUtil.jiemi(dbPassword);
            dbSource.setDbPassword(decodedStr);
        }
        return new DynamicDataSourceModel(dbSource);
    }

    @Override
    public DynamicDataSourceModel getDynamicDbSourceByCode(String dbSourceCode) {
        SysDataSource dbSource = dataSourceService.getOne(new LambdaQueryWrapper<SysDataSource>().eq(SysDataSource::getCode, dbSourceCode));
        if (dbSource != null && StringUtils.isNotBlank(dbSource.getDbPassword())) {
            String dbPassword = dbSource.getDbPassword();
            String decodedStr = SecurityUtil.jiemi(dbPassword);
            dbSource.setDbPassword(decodedStr);
        }
        return new DynamicDataSourceModel(dbSource);
    }

    @Override
    public List<String> getDeptHeadByDepId(String deptId) {
        List<SysUsers> userList = userMapper.selectList(new QueryWrapper<SysUsers>().like("depart_ids", deptId).eq("status", 1).eq("del_flag", 0));
        List<String> list = new ArrayList<>();
        for (SysUsers user : userList) {
            list.add(user.getUsername());
        }
        return list;
    }

    @Override
    public void sendWebSocketMsg(String[] userIds, String cmd) {
        JSONObject obj = new JSONObject();
        obj.put(WebsocketConst.MSG_CMD, cmd);
        WebSocket.sendMoreMessage(userIds, obj.toJSONString());
    }

    @Override
    public List<LoginUser> queryAllUserByIds(String[] userIds) {
        QueryWrapper<SysUsers> queryWrapper = new QueryWrapper<SysUsers>().eq("status", 1).eq("del_flag", 0);
        queryWrapper.in("id", userIds);
        List<LoginUser> loginUsers = new ArrayList<>();
        List<SysUsers> sysUsers = userMapper.selectList(queryWrapper);
        for (SysUsers user : sysUsers) {
            LoginUser loginUser = new LoginUser();
            BeanUtils.copyProperties(user, loginUser);
            loginUsers.add(loginUser);
        }
        return loginUsers;
    }

    /**
     * 推送签到人员信息
     *
     * @param userId
     */
    @Override
    public void meetingSignWebsocket(String userId) {
        JSONObject obj = new JSONObject();
        obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_SIGN);
        obj.put(WebsocketConst.MSG_USER_ID, userId);
        //TODO 目前全部推送，后面修改
        //WebSocket.sendAllMessage(obj.toJSONString());
        redisMq.publish(Streams.WEBSOCKET_PUBLICIZE, obj);
    }

    @Override
    public List<LoginUser> queryUserByNames(String[] userNames) {
        QueryWrapper<SysUsers> queryWrapper = new QueryWrapper<SysUsers>().eq("status", 1).eq("del_flag", 0);
        queryWrapper.in("username", userNames);
        List<LoginUser> loginUsers = new ArrayList<>();
        List<SysUsers> sysUsers = userMapper.selectList(queryWrapper);
        for (SysUsers user : sysUsers) {
            LoginUser loginUser = new LoginUser();
            BeanUtils.copyProperties(user, loginUser);
            loginUsers.add(loginUser);
        }
        return loginUsers;
    }

    @Override
    public SysDepartModel selectAllById(String id) {
        SysDepart sysDepart = sysDepartService.getById(id);
        if (sysDepart == null) {
            return null;
        }
        SysDepartModel sysDepartModel = new SysDepartModel();
        BeanUtils.copyProperties(sysDepart, sysDepartModel);
        return sysDepartModel;
    }

    @Override
    public String selectDepartNameById(String departId) {
        SysDepart sysDepart = sysDepartService.getById(departId);
        if (sysDepart == null) {
            return null;
        }
        return sysDepart.getDepartName();
    }

    @Override
    public List<String> queryDeptUsersByUserId(String userId) {
        List<String> userIds = new ArrayList<>();
        List<SysUserDepart> userDepartList = sysUserDepartService.list(new QueryWrapper<SysUserDepart>().eq("user_id", userId));
        if (userDepartList != null) {
            //查找所属公司
            String orgCodes = "";
            for (SysUserDepart userDepart : userDepartList) {
                //查询所属公司编码
                SysDepart depart = sysDepartService.getById(userDepart.getDepId());
                int length = YouBianCodeUtil.zhanweiLength;
                String compyOrgCode = "";
                if (depart != null && depart.getOrgCode() != null) {
                    compyOrgCode = depart.getOrgCode().substring(0, length);
                    if (orgCodes.indexOf(compyOrgCode) == -1) {
                        orgCodes = orgCodes + "," + compyOrgCode;
                    }
                }
            }
            if (oConvertUtils.isNotEmpty(orgCodes)) {
                orgCodes = orgCodes.substring(1);
                List<String> listIds = departMapper.getSubDepIdsByOrgCodes(orgCodes.split(","));
                List<SysUserDepart> userList = sysUserDepartService.list(new QueryWrapper<SysUserDepart>().in("dep_id", listIds));
                for (SysUserDepart userDepart : userList) {
                    if (!userIds.contains(userDepart.getUserId())) {
                        userIds.add(userDepart.getUserId());
                    }
                }
            }
        }
        return userIds;
    }

    /**
     * 查询用户拥有的角色集合
     *
     * @param username
     * @return
     */
    @Override
    public Set<String> getUserRoleSet(String username) {
        // 查询用户拥有的角色集合
        List<String> roles = sysUserRoleMapper.getRoleByUserName(username);
        log.info("-------通过数据库读取用户拥有的角色Rules------username： " + username + ",Roles size: " + (roles == null ? 0 : roles.size()));
        return new HashSet<>(roles);
    }

    /**
     * 查询用户拥有的权限集合
     *
     * @param username
     * @return
     */
    @Override
    public Set<String> getUserPermissionSet(String username) {
        Set<String> permissionSet = new HashSet<>();
        List<SysPermission> permissionList = sysPermissionMapper.queryByUser(username);
        for (SysPermission po : permissionList) {
//			// TODO URL规则有问题？
//			if (oConvertUtils.isNotEmpty(po.getUrl())) {
//				permissionSet.add(po.getUrl());
//			}
            if (oConvertUtils.isNotEmpty(po.getPerms())) {
                permissionSet.add(po.getPerms());
            }
        }
        log.info("-------通过数据库读取用户拥有的权限Perms------username： " + username + ",Perms size: " + (permissionSet == null ? 0 : permissionSet.size()));
        return permissionSet;
    }

    /**
     * 判断online菜单是否有权限
     *
     * @param onlineAuthDTO
     * @return
     */
    @Override
    public boolean hasOnlineAuth(OnlineAuthDTO onlineAuthDTO) {
        String username = onlineAuthDTO.getUsername();
        List<String> possibleUrl = onlineAuthDTO.getPossibleUrl();
        String onlineFormUrl = onlineAuthDTO.getOnlineFormUrl();
        //查询菜单
        LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>();
        query.eq(SysPermission::getDelFlag, 0);
        query.in(SysPermission::getUrl, possibleUrl);
        List<SysPermission> permissionList = sysPermissionMapper.selectList(query);
        if (permissionList == null || permissionList.size() == 0) {
            //没有配置菜单 找online表单菜单地址
            SysPermission sysPermission = new SysPermission();
            sysPermission.setUrl(onlineFormUrl);
            int count = sysPermissionMapper.queryCountByUsername(username, sysPermission);
            if (count <= 0) {
                return false;
            }
        } else {
            //找到菜单了
            boolean has = false;
            for (SysPermission p : permissionList) {
                int count = sysPermissionMapper.queryCountByUsername(username, p);
                has = has || (count > 0);
            }
            return has;
        }
        return true;
    }

    /**
     * 查询用户拥有的角色集合 common api 里面的接口实现
     *
     * @param username
     * @return
     */
    @Override
    public Set<String> queryUserRoles(String username) {
        return getUserRoleSet(username);
    }

    /**
     * 查询用户拥有的权限集合 common api 里面的接口实现
     *
     * @param username
     * @return
     */
    @Override
    public Set<String> queryUserAuths(String username) {
        return getUserPermissionSet(username);
    }

    /**
     * 36根据多个用户账号(逗号分隔)，查询返回多个用户信息
     *
     * @param usernames
     * @return
     */
    @Override
    public List<JSONObject> queryUsersByUsernames(String usernames) {
        LambdaQueryWrapper<SysUsers> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SysUsers::getUsername, usernames.split(","));
        return JSON.parseArray(JSON.toJSONString(userMapper.selectList(queryWrapper))).toJavaList(JSONObject.class);
    }

    /**
     * 37根据多个部门编码(逗号分隔)，查询返回多个部门信息
     *
     * @param orgCodes
     * @return
     */
    @Override
    public List<JSONObject> queryDepartsByOrgcodes(String orgCodes) {
        LambdaQueryWrapper<SysDepart> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SysDepart::getOrgCode, orgCodes.split(","));
        return JSON.parseArray(JSON.toJSONString(sysDepartService.list(queryWrapper))).toJavaList(JSONObject.class);
    }

    /**
     * 发消息
     *
     * @param fromUser
     * @param toUser
     * @param title
     * @param msgContent
     * @param setMsgCategory
     */
    public void sendSysAnnouncement(String fromUser, String toUser, String title, String msgContent, String setMsgCategory, Integer priority) {
        // 1.插入系统通告表记录
        SysAnnouncement announcement = new SysAnnouncement();
        announcement.setTitile(title);
        announcement.setMsgContent(msgContent);
        announcement.setSender(fromUser);
        announcement.setPriority(getPriority(priority.toString()));
        announcement.setMsgType(CommonConstant.MSG_TYPE_UESR);
        announcement.setSendStatus(CommonConstant.HAS_SEND);
        announcement.setSendTime(new Date());
        announcement.setMsgCategory(setMsgCategory);
        announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
        sysAnnouncementMapper.insert(announcement);
        // 2.插入用户通告阅读标记表记录
        String userId = toUser;
        String[] userIds = userId.split(",");
        String anntId = announcement.getId();
        for (int i = 0; i < userIds.length; i++) {
            if (oConvertUtils.isNotEmpty(userIds[i])) {
                SysUsers sysUser = userMapper.getUserByName(userIds[i]);
                if (sysUser == null) {
                    continue;
                }
                SysAnnouncementSend announcementSend = new SysAnnouncementSend();
                announcementSend.setAnntId(anntId);
                announcementSend.setUserId(sysUser.getId());
                announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
                sysAnnouncementSendMapper.insert(announcementSend);
                JSONObject obj = new JSONObject();
                obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
                obj.put(WebsocketConst.MSG_USER_ID, sysUser.getId());
                obj.put(WebsocketConst.MSG_ID, announcement.getId());
                obj.put(WebsocketConst.MSG_TXT, announcement.getTitile());
                WebSocket.sendOneMessage(sysUser.getId(), obj.toJSONString());
            }
        }

    }

    /**
     * 发消息 带业务参数
     *
     * @param fromUser
     * @param toUser
     * @param title
     * @param msgContent
     * @param setMsgCategory
     * @param busType
     * @param busId
     */
    private void sendBusAnnouncement(String fromUser, String toUser, String title, String msgContent, String setMsgCategory, String busType, String busId, Integer priority) {
        SysAnnouncement announcement = new SysAnnouncement();
        announcement.setTitile(title);
        announcement.setMsgContent(msgContent);
        announcement.setSender(fromUser);
        announcement.setPriority(getPriority(priority.toString()));
        announcement.setMsgType(CommonConstant.MSG_TYPE_UESR);
        announcement.setSendStatus(CommonConstant.HAS_SEND);
        announcement.setSendTime(new Date());
        announcement.setMsgCategory(setMsgCategory);
        announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
        announcement.setBusId(busId);
        announcement.setBusType(busType);
        announcement.setOpenType(SysAnnmentTypeEnum.getByType(busType).getOpenType());
        announcement.setOpenPage(SysAnnmentTypeEnum.getByType(busType).getOpenPage());
        sysAnnouncementMapper.insert(announcement);
        // 2.插入用户通告阅读标记表记录
        String userId = toUser;
        String[] userIds = userId.split(",");
        String anntId = announcement.getId();
        for (int i = 0; i < userIds.length; i++) {
            if (oConvertUtils.isNotEmpty(userIds[i])) {
                SysUsers sysUser = userMapper.getUserByName(userIds[i]);
                if (sysUser == null) {
                    continue;
                }
                SysAnnouncementSend announcementSend = new SysAnnouncementSend();
                announcementSend.setAnntId(anntId);
                announcementSend.setUserId(sysUser.getId());
                announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
                sysAnnouncementSendMapper.insert(announcementSend);
                JSONObject obj = new JSONObject();
                obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_USER);
                obj.put(WebsocketConst.MSG_USER_ID, sysUser.getId());
                obj.put(WebsocketConst.MSG_ID, announcement.getId());
                obj.put(WebsocketConst.MSG_TXT, announcement.getTitile());
                WebSocket.sendOneMessage(sysUser.getId(), obj.toJSONString());
            }
        }
    }

    /**
     * @param priority
     * @return
     */
    private String getPriority(String priority) {
        String msgPriority = CommonConstant.PRIORITY_H;
        if ("0".equals(priority)) {
            msgPriority = CommonConstant.PRIORITY_L;
        } else if ("1".equals(priority)) {
            msgPriority = CommonConstant.PRIORITY_M;
        }
        return msgPriority;
    }

    @Override
    public List<JSONObject> getRoleByUsername(String username) {
        return sysUserRoleMapper.getRoleByUsername(username);
    }

    @Override
    public List<com.insight.common.system.vo.SysAnnouncement> getByBusId(String taskId) {
        List<SysAnnouncement> list = new LambdaQueryChainWrapper<>(sysAnnouncementMapper).eq(SysAnnouncement::getBusId, taskId).list();
        return list.stream().map(sysAnnouncement -> {
            com.insight.common.system.vo.SysAnnouncement sysAnnouncement1 = new com.insight.common.system.vo.SysAnnouncement();
            BeanUtils.copyProperties(sysAnnouncement, sysAnnouncement1);
            return sysAnnouncement1;
        }).collect(Collectors.toList());
    }

    @Override
    public void updatesysAnnouncementById(com.insight.common.system.vo.SysAnnouncement sysAnnouncement) {
        SysAnnouncement sysAnnouncement1 = new SysAnnouncement();
        BeanUtils.copyProperties(sysAnnouncement, sysAnnouncement1);
        sysAnnouncementMapper.updateById(sysAnnouncement1);
    }

    @Override
    public List<com.insight.common.system.vo.SysAnnouncementSend> listBySysAnnouncementId(String id) {
        List<SysAnnouncementSend> list = new LambdaQueryChainWrapper<>(sysAnnouncementSendMapper).eq(SysAnnouncementSend::getAnntId, id).list();
        return list.stream().map(sysAnnouncementSend -> {
            com.insight.common.system.vo.SysAnnouncementSend sysAnnouncementSend1 = new com.insight.common.system.vo.SysAnnouncementSend();
            BeanUtils.copyProperties(sysAnnouncementSend, sysAnnouncementSend1);
            return sysAnnouncementSend1;
        }).collect(Collectors.toList());
    }

    @Override
    public void updatesysAnnouncemenSendtById(com.insight.common.system.vo.SysAnnouncementSend one) {
        SysAnnouncementSend sysAnnouncementSend = new SysAnnouncementSend();
        BeanUtils.copyProperties(one, sysAnnouncementSend);
        sysAnnouncementSendMapper.updateById(sysAnnouncementSend);
    }

    /**
     * 根据字典code查询字典项
     *
     * @param dictCode 顺序：tableName,text,code
     * @param dictCode 要查询的key
     * @return
     */
    @Override
    public List<DictModel> getDictItems(String dictCode) {
        List<DictModel> ls = sysDictService.getDictItems(dictCode);
        if (ls == null) {
            ls = new ArrayList<>();
        }
        return ls;
    }

    @Override
    public SysCategoryModel getCategoryDictById(String id) {
        SysCategory sysCategory = sysCategoryService.getById(id);

        SysCategoryModel sysCategoryModel = new SysCategoryModel();
        if (sysCategory != null) {
            sysCategoryModel.setCode(sysCategory.getCode());
            sysCategoryModel.setId(sysCategory.getId());
            sysCategoryModel.setName(sysCategory.getName());
            sysCategoryModel.setPid(sysCategory.getPid());
            return sysCategoryModel;
        }
        return null;
    }

    @Override
    public List<SysDepartModel> getDepartNameByCodes(String[] departCodes) {
        List<SysDepart> sysDeparts = sysDepartService.queryByCodes(departCodes);
        List<SysDepartModel> sysDepartModelList = new ArrayList<>();
        for (SysDepart sysDepart : sysDeparts) {
            SysDepartModel sysDepartModel = new SysDepartModel();
            BeanUtils.copyProperties(sysDepart, sysDepartModel);
            sysDepartModelList.add(sysDepartModel);
        }

        return sysDepartModelList;
    }

    @Override
    public LoginUser queryUserByName(String userName) {
        QueryWrapper<SysUsers> queryWrapper = new QueryWrapper<SysUsers>().eq("status", 1).eq("del_flag", 0);
        queryWrapper.eq("username", userName);
        LoginUser loginUser = new LoginUser();
        SysUsers sysUser = userMapper.selectOne(queryWrapper);
        BeanUtils.copyProperties(sysUser, loginUser);
        return loginUser;
    }

    @Override
    public List<LoginUser> listUsersByRoleCode(String roleCodes) {
        return userMapper.listUsersByRoleCode(roleCodes);
    }

    @Override
    public List<SysCategoryModel> querySysCategoryByParentIdWithPage(String serviceTypePid, Integer pageNo, Integer pageSize) {
        Integer currIndex = (pageNo - 1) * pageSize;
        List<SysCategory> ls = categoryMapper.querySysCategoryByParentIdWithPage(serviceTypePid, currIndex, pageSize);
        return oConvertUtils.entityListToModelList(ls, SysCategoryModel.class);
    }

    @Override
    public List<SysCategoryModel> querySysCategoryByParentId(String pid) {
        List<SysCategory> ls = categoryMapper.querySysCategoryByParentId(pid);
        return oConvertUtils.entityListToModelList(ls, SysCategoryModel.class);
    }

    @Override
    public List<String> querySysCategoryByCode(String code) {
        return categoryMapper.querySysCategoryByCode(code);
    }

    @Override
    public List<SysDepartModel> queryDepartsByUsername(String batchApply) {
        return sysUserDepartService.queryDepartsByUsername(batchApply);
    }

    @Override
    public List<String> getUserByNames(List<String> users) {
        return userMapper.getUserByNames(users);
    }

    @Override
    public List<String> getDepartIdByUserId(String userid) {
        return userMapper.getDepartIdByUserId(userid);
    }

    /**
     * 发送流程系统通知
     *
     * @param templateParam
     * @param templateCode
     * @param users
     */
    @Override
    @Transactional
    public void sendNoticeByProcess(Map<String, String> templateParam, String templateCode, List<String> users) {
        SysNoticeTemplate sysNoticeTemplate = sysNoticeTemplateService.getById(templateCode);
        if (sysNoticeTemplate == null) {
            throw new NullPointerException("配置模板不能为空！");
        }
        //获取通知配置
        MPJLambdaWrapper<SysNoticeConfig> wrapper = new MPJLambdaWrapper<SysNoticeConfig>().selectAll(SysNoticeConfig.class).selectCollection(SysNoticeExtend.class, SysNoticeConfig::getExtend).leftJoin(SysNoticeExtend.class, SysNoticeExtend::getNoticeConfigId, SysNoticeConfig::getId).eq(SysNoticeConfig::getId, sysNoticeTemplate.getNoticeConfigId());
        SysNoticeConfig noticeConfig = noticeConfigService.selectJoinOne(SysNoticeConfig.class, wrapper);
        //获取通知模板设置
        JSONObject template = JSON.parseObject(sysNoticeTemplate.getTemplate());
        template.put("par", templateParam);
        template.put("title", sysNoticeTemplate.getTemplateName());
        //设置收消息人
        List<String> userIds = getUserByNames(users);
        JSONArray jsonArray = new JSONArray();
        jsonArray.addAll(userIds);
        template.put("sendTo", jsonArray.toJSONString());
        //组装消息体
        JSONObject msgData = new JSONObject();
        msgData.put("support", noticeConfig.getConfigType());
        msgData.put("template", template);
        msgData.put("isPar", CollUtil.isNotEmpty(templateParam));

        //email的额外信息，email已做测试，其他的未测试.sendMsg是一个类,也有对应的getSendMsg的方法
        // （有三个地方都写了同样功能的方法，SendContentListener，SysNoticeExtendServiceImpl，DevopsAutoInspectionReportServiceImpl）addInfo()方法的功能一样
        msgData.put("sendMsg", addInfo(noticeConfig));//sendMsg这个key名字的由来是NoticeEventListener
        //模板内容
        String content = template.getString("content");
        for (Map.Entry<String, String> entry : templateParam.entrySet()) {
            String str = "${" + entry.getKey() + "}";
            content = content.replace(str, entry.getValue());
        }

        //添加系统通告表
        SysAnnouncement announcement = addSysAnnouncement(sysNoticeTemplate.getTemplateName(), content);

        for (String user : users) {
            SysUsers sysUser = userMapper.getUserByName(user);
            SysAnnouncementSend announcementSend = new SysAnnouncementSend();
            announcementSend.setAnntId(announcement.getId());
            announcementSend.setUserId(sysUser.getId());
            announcementSend.setReadFlag(CommonConstant.NO_READ_FLAG);
            sysAnnouncementSendMapper.insert(announcementSend);
        }
        redisMq.publish(Streams.NOTICE, msgData);
    }

    JSONObject addInfo(SysNoticeConfig noticeConfig) {
        JSONObject o = new JSONObject();
        List<SysNoticeExtend> extendList = noticeConfig.getExtend();
        for (SysNoticeExtend e : extendList) {
            o.put(e.getFieldCode(), e.getFieldValue());
        }
        return o;
    }

    /**
     * 根据菜单id获取菜单信息
     *
     * @param menuId
     * @return
     */
    @Override
    public Integer getMenPlatformTypeById(String menuId) {
        SysPermission sysPermission = iSysPermissionService.getById(menuId);
        return sysPermission.getPlatformType();
    }

    @Override
    public List<String> getRealNameByNames(List<String> userNames) {
        return userMapper.getRealNameByNames(userNames);
    }

    /**
     * 添加系统通告表
     *
     * @param templateName
     * @param content
     * @return
     */
    private SysAnnouncement addSysAnnouncement(String templateName, String content) {
        //添加系统通知信息
        SysAnnouncement announcement = new SysAnnouncement();
        announcement.setTitile(templateName);
        announcement.setMsgContent(content);
        try {
            announcement.setSender(com.yuanqiao.insight.common.core.util.SecurityUtils.getUser().getUsername());
        } catch (UnavailableSecurityManagerException e) {
            announcement.setSender("system_auto_publish");
        }
        announcement.setPriority(CommonConstant.PRIORITY_M);
        announcement.setMsgType(CommonConstant.MSG_TYPE_UESR);
        announcement.setSendStatus(CommonConstant.HAS_SEND);
        announcement.setSendTime(new Date());
        announcement.setMsgCategory(CommonConstant.MSG_CATEGORY_2);
        announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
        sysAnnouncementMapper.insert(announcement);
        return announcement;
    }


    @Override
    public List<String> queryDepartIdsByAdCode(String adCode) {
        return departMapper.queryListByAdCode(adCode);
    }


    @Transactional
    @Override
    public void deleteAnnouncementByBusId(String taskId) {
        sysAnnouncementMapper.delete(new QueryWrapper<SysAnnouncement>().eq("bus_id", taskId));
    }

    @Override
    public Map<String, SysDepartModel> queryDepartsByUserIds(List<String> users) {
        List<SysUserDepVo> list = userMapper.getDepNamesByUserIds(users);
        Map<String, SysDepartModel> res = new HashMap(5);

        list.forEach(item -> {

                    if (res.get(item.getUserId()) == null) {
                        SysDepartModel sysDepartModel = new SysDepartModel();
                        sysDepartModel.setDepartName(item.getDepartName());
                        sysDepartModel.setId(item.getDepartId());
                        res.put(item.getUserId(), sysDepartModel);
                    } else {
                        SysDepartModel sysDepartModel = res.get(item.getUserId());
                        sysDepartModel.setDepartName(sysDepartModel.getDepartName() + "," + item.getDepartName());
                        sysDepartModel.setId(sysDepartModel.getId() + "," + item.getDepartId());
                    }
                }
        );
        return res;
    }

    @Override
    public Map<String, LoginUser> getRoleByUserIdList(List<String> users) {
        List<SysUserRoleVO> roleByUserIdList = sysUserRoleMapper.getRoleByUserIdList(users);
        Map<String, LoginUser> res = new HashMap(5);

        roleByUserIdList.forEach(item -> {
                    if (res.get(item.getUserId()) == null) {
                        LoginUser loginUser = new LoginUser();
                        loginUser.setRoleCodes(item.getRoleId());
                        loginUser.setRoleNames(item.getRoleName());
                        loginUser.setId(item.getUserId());
                        res.put(item.getUserId(), loginUser);
                    } else {
                        LoginUser loginUser = res.get(item.getUserId());
                        loginUser.setRoleCodes(loginUser.getRoleCodes() + "," + item.getRoleId());
                        loginUser.setRoleNames(loginUser.getRoleNames() + "," + item.getRoleName());
                    }
                }
        );
        return res;
    }

    /**
     * 根据id获取单位名称
     *
     * @param id
     * @return
     */
    @Override
    public String getDepartNameById(String id) {
        SysDepart sysDepart = sysDepartService.getById(id);
        if (sysDepart != null) {
            return sysDepart.getDepartName();
        }
        return "";
    }

    @Override
    public List<JSONObject> getPermissionData(List<String> ids) {
        boolean notEmpty = CollUtil.isNotEmpty(ids);
        List<SysPermission> sysPermissions = sysPermissionMapper.selectList(new LambdaQueryWrapper<SysPermission>()
                .in(notEmpty, SysPermission::getId, ids)
                .eq(SysPermission::getDelFlag, 0));
        List<JSONObject> list = new ArrayList<>();
        JSONObject clientId = JSON.parseObject(String.valueOf(Optional.ofNullable(cacheUtils.getValue("oauth2_clientId")).orElse("{}")));
        if (CollUtil.isNotEmpty(sysPermissions)) {
            list = sysPermissions.stream()
                    .map(sysPermission -> {
                        JSONObject mappingMenu = sysPermission.getMappingMenu();
                        mappingMenu.put("sysIsDel", notEmpty ? 1 : 0);
                        mappingMenu.put("clientId", clientId.get(sysPermission.getPlatformType() + ""));
                        return mappingMenu;
                    }).collect(Collectors.toList());
        }

        return list;
    }

    @Override
    public List<String> getPerms(List<String> ids) {
        List<SysPermission> sysPermissions = sysPermissionMapper.selectList(new LambdaQueryWrapper<SysPermission>()
                .in(SysPermission::getId, ids)
                .isNotNull(SysPermission::getPerms)
                .eq(SysPermission::getDelFlag, 0));
        return sysPermissions.stream()
                .map(SysPermission::getPerms)
                .collect(Collectors.toList());
    }

    @Override
    public void setUserPermission(Set<String> roleSet, List<String> ids) {
        if (CollUtil.isNotEmpty(ids)) {
            List<SysRole> sysRoles = roleMapper.selectList(new LambdaQueryWrapper<SysRole>().in(SysRole::getRoleCode, roleSet));
            List<String> collect = sysRoles.stream().map(SysRole::getId).collect(Collectors.toList());
            sysRolePermissionMapper.delete(new LambdaQueryWrapper<SysRolePermission>().in(SysRolePermission::getRoleId, collect));
            collect.forEach(roleId -> {
                ids.forEach(id -> {
                    SysRolePermission rolePermission = new SysRolePermission();
                    rolePermission.setRoleId(roleId);
                    rolePermission.setPermissionId(id);
                    sysRolePermissionMapper.insert(rolePermission);
                });

            });
        }
    }
}
